package name.sra.editor;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;

import name.sra.util.ImageLine;
import name.sra.util.RgbUtils;

public class ImageEditor {
	protected File img;
	protected BufferedImage inputImage;
	protected BufferedImage outputImage;

	protected List<ImageLine> precedingLines;
	protected List<ImageLine> contiguousLines;
	protected List<ImageLine> colorizedLines;
	
	long startTime;
	private double level;
	private int currentRow;
	private long countLoops = 0;
	
	private static int ERASOR_COLOR = 0xFF00008B;
	
	public ImageEditor(File img) {
		super();
		this.img = img;
		try {
			inputImage = ImageIO.read(img);
			outputImage = ImageIO.read(img);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public BufferedImage eraseClearPixel(double level) throws Exception {
		for (int i = 0;i < inputImage.getWidth(); i++) {
			for (int j = 0;j < inputImage.getHeight();j++) {
				int rgb = inputImage.getRGB(i, j);
				double value = RgbUtils.calculateIntensity(
											Integer.toHexString(rgb));
				if (value < level) {
					outputImage.setRGB(i, j, ERASOR_COLOR);
				}
			}
		}
		return outputImage;
	}
	
	public BufferedImage eraseBordersClearPixel(double level) throws Exception {
		
		for (int row = 0;row < inputImage.getHeight();row++) {
			ImageLine line = new ImageLine(inputImage, outputImage, row);
			line.calculateContiguousLines(level);
			List<ImageLine> contiguousLines = line.getContiguousLines();
			contiguousLines.get(0).colorize(ERASOR_COLOR);
			contiguousLines.get(contiguousLines.size() - 1).colorize(ERASOR_COLOR);
		}
		return outputImage;
	}
	
	
	public BufferedImage eraseOverlappingClearPixelDownwards(double aLevel)
															throws Exception {
		level = aLevel;

		ImageLine line = new ImageLine(inputImage, outputImage, 0);
		line.calculateContiguousLines(level);
		precedingLines = line.getContiguousLines();
		eraseAllLines(precedingLines);
		
		for (currentRow = 1;currentRow < inputImage.getHeight();currentRow++) {
			eraseRowsOverlappingBits();
		}
		return outputImage;
	}

	private void eraseRowsOverlappingBits() {
		ImageLine line;
		colorizedLines = new ArrayList<ImageLine>();
		line = new ImageLine(inputImage, outputImage, currentRow);
		line.calculateContiguousLines(level);
		contiguousLines = line.getContiguousLines();
		eraseOverlappingLines();
		precedingLines = colorizedLines;
	}
	
	private void eraseOverlappingLines() {
		Iterator<ImageLine> contIt = contiguousLines.iterator();
		while (contIt.hasNext()) {
			ImageLine current = contIt.next();

			Iterator<ImageLine> precIt = precedingLines.iterator();
			while (precIt.hasNext()) {
				ImageLine precCurrent = precIt.next();
				if (current.horizontallyOverlaps(precCurrent)) {
					current.colorize(ERASOR_COLOR);
					colorizedLines.add(current);
					countLoops++;
					break;
				}
			}
		}
	}

	public BufferedImage eraseOverlappingClearPixelUpwards(double aLevel)
															throws Exception {
		level = aLevel;
		
		ImageLine line = new ImageLine(inputImage, outputImage, inputImage.getHeight() - 1);
		line.calculateContiguousLines(level);
		precedingLines = line.getContiguousLines();
		eraseAllLines(precedingLines);
		
		for (currentRow = inputImage.getHeight() - 2;currentRow > -1;currentRow--) {
			eraseRowsOverlappingBits();
		}
		return outputImage;
	}
	
	public void eraseClearPixelZone(double aLevel, int x, int y) {
		int rgb = inputImage.getRGB(x, y);
		double value = RgbUtils.calculateIntensity(Integer.toHexString(rgb));
		if (value > level) {
			return;
		}
		ImageLine firstLine = getImageLine(aLevel, x, y);
		firstLine.colorize(ERASOR_COLOR);
	}
	
	private ImageLine getImageLine(double level2, int x, int y) {
		ImageLine dot = new ImageLine(inputImage, outputImage, y, x, x);
		ImageLine wholeLines = new ImageLine(inputImage, outputImage, y);
		wholeLines.calculateContiguousLines(level2);
		List<ImageLine> lines = wholeLines.getContiguousLines();
		Iterator<ImageLine> it = lines.iterator();
		ImageLine result = null;
		while (it.hasNext()) {
			result = it.next();
			if (dot.horizontallyOverlaps(result)) {
				break;
			}
		}
		return result;
	}

	private void report() {
		System.out.println(getTime() - startTime + "ms");
		System.out.println("nb object en memmoire : "
										+ ImageLine.count);
		System.out.println("still alives : " + (ImageLine.count - ImageLine.finalizeCount));
		System.out.println("count loops : " + countLoops);
	}

	private long getTime() {
		return Calendar.getInstance().getTimeInMillis();
	}

	private void eraseAllLines(List<ImageLine> lines) {
		Iterator<ImageLine> lineIt = lines.iterator();
		while (lineIt.hasNext()) {
			lineIt.next().colorize(ERASOR_COLOR);
		}
	}
}
